import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { LessThan, Repository, Between, Like } from 'typeorm';
import { OperationLogEntity } from '../entities/operation-log.entity';
import { paginate } from '~/helper/paginate';
import { operationLogQueryDto } from '../dto/log.dto';
import { formatToDateTime } from '../../../../utils';
import { OperationLogInfo } from '../models/log.model';

async function parseOperationLog(elem: any): Promise<OperationLogInfo> {
  return {
    id: elem.id,
    module: elem.module,
    actionType: elem.actionType,
    duration: elem.duration,
    createdAt: formatToDateTime(elem.createdAt),
  };
}

@Injectable()
export class OperationLogService {
  constructor(
    @InjectRepository(OperationLogEntity)
    private readonly operationLogRepository: Repository<OperationLogEntity>
  ) {}

  async create(
    uid: number,
    module: string,
    actionType: string,
    duration: number,
    request?: string,
    response?: string
  ): Promise<number> {
    const result = await this.operationLogRepository.save({
      module: module,
      actionType: actionType,
      duration: duration,
      user: { id: uid },
      request: request ?? '',
      response: response ?? '',
    });
    return result.id;
  }

  async list({
    page,
    pageSize,
    username,
    module,
    actionType,
    duration,
    operationTime,
  }: operationLogQueryDto) {
    const queryBuilder = await this.operationLogRepository
      .createQueryBuilder('operation_log')
      .innerJoinAndSelect('operation_log.user', 'user')
      .where({
        ...(module && { module: Like(`%${module}%`) }),
        ...(actionType && { actionType: Like(`%${actionType}%`) }),
        ...(duration && { duration: LessThan(duration) }),
        ...(operationTime && {
          createdAt: Between(operationTime[0], operationTime[1]),
        }),
        ...(username && {
          user: {
            username: Like(`%${username}%`),
          },
        }),
      })
      .orderBy('operation_log.createdAt', 'DESC');

    const { items, ...rest } = await paginate<OperationLogEntity>(
      queryBuilder,
      {
        page,
        pageSize,
      }
    );

    const loginLogInfos = await Promise.all(
      items.map(item => parseOperationLog(item))
    );

    return {
      items: loginLogInfos,
      ...rest,
    };
  }

  async clearLog(): Promise<void> {
    await this.operationLogRepository.clear();
  }

  async clearLogBeforeTime(time: Date): Promise<void> {
    await this.operationLogRepository.delete({ createdAt: LessThan(time) });
  }
}
